﻿using gixoom.Dom.Score;

namespace gixoom.Dom.Block
{
    public interface IBlockFacade
    {
        /// <summary>
        /// Creates and returns block id object from the specified block type and score.
        /// </summary>
        /// <param name="blockType">block type</param>
        /// <param name="score">block's score</param>
        /// <returns>created block id</returns>
        /// <exception cref="System.ArgumentNullException"><i>score</i> is a null reference.</exception>
        IBlockId CreateBlockId(BlockType blockType, IScore score);

        /// <summary>
        /// Creates block id object from the specified array of bytes where the first byte
        /// represents a block type and all the other bytes represent a score.
        /// </summary>
        /// <param name="bytes">the array to create block id object from</returns>
        /// <exception cref="System.ArgumentNullException"><i>bytes</i> is a null reference.</exception>
        /// <exception cref="System.ArgumentException"><i>bytes</i> length is invalid.</exception>
        IBlockId CreateBlockIdFromBytes(byte[] bytes);

        /// <summary>
        /// Creates block id object from the specified array of bytes starting with the specified index
        /// where the first byte represents a block type and all the other bytes represent a score.
        /// </summary>
        /// <param name="bytes">the input from which to create block id from</param>
        /// <returns>created block id</returns>
        /// <param name="bytesIndex">the index in the array at which the bytes should be read</param>
        /// <exception cref="System.ArgumentNullException"><i>bytes</i> is a null reference.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException"><i>bytesIndex</i> doesn't fall into
        /// the <i>bytes</i> boundaries.</exception>
        /// <exception cref="System.ArgumentException"><i>bytesIndex</i> or <i>bytes</i> length is invalid.</exception>
        IBlockId CreateBlockIdFromBytes(byte[] bytes, int bytesIndex);

        /// <summary>
        /// Serializes the specified block id to the specified array starting with the specified index.
        /// </summary>
        /// <param name="blockId">the block id which should be serialized</param>
        /// <param name="array">the array where the serialized block id should be stored</param>
        /// <param name="arrayIndex">the array index at which the serialized block id
        /// should be stored in the array</param>
        /// <returns>the next index in the array</returns>
        /// <exception cref="System.ArgumentNullException">One of the arguments is a null reference.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException"><i>arrayIndex</i> doesn't fall into
        /// the <i>array</i> boundaries.</exception>
        /// <exception cref="System.ArgumentException"><i>arrayIndex</i> or <i>array</i> length is invalid.</exception>
        int SerializeBlockId(IBlockId blockId, byte[] array, int arrayIndex);

        /// <summary>
        /// Serializes the specified block id and returns a new array of block id bytes.
        /// </summary>
        /// <param name="blockId">the block id</param>
        /// <returns>the new array of the block id bytes</returns>
        /// <exception cref="System.ArgumentNullException"><i>blockId</i> is a null reference.</exception>
        byte[] SerializeBlockId(IBlockId blockId);

        /// <summary>
        /// Creates block object from the specified block type and the specified content.
        /// </summary>
        /// <param name="blockType">block type</param>
        /// <param name="content">the content which should be used to create the block</param>
        /// <returns>created block object</returns>
        /// <exception cref="System.ArgumentNullException"><i>content</i> is a null reference.</exception>
        IBlock CreateBlockFromContent(BlockType blockType, byte[] content);

        /// <summary>
        /// Creates block object from the specified range of the specified array.
        /// </summary>
        /// <param name="blockType">block type</param>
        /// <param name="content">the input to create block object for</param>
        /// <param name="offset">the offset into the byte array from which to begin using data</param>
        /// <param name="count">the number of bytes in the array to use as data</param>
        /// <returns>created block object</returns>
        /// <exception cref="System.ArgumentNullException"><i>content</i> is a null reference.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException"><i>offset</i> is out of range.
        /// This parameter requires a non-negative number which is less than the <i>content</i> length.</exception>
        /// <exception cref="System.ArgumentException"><i>count</i> is an invalid value or <i>content</i> length 
        /// is invalid.</exception>
        IBlock CreateBlockFromContent(BlockType blockType, byte[] content, int offset, int count);

        /// <summary>
        /// Creates block object from the specified array. The first element in the array
        /// is a block type. The next elements represent a score and all the other elements
        /// are a content.
        /// </summary>
        /// <param name="bytes">the input to create block object from</param>
        /// <returns>created block object or null if it cannot be created
        /// due to array inconsistency</returns>
        /// <exception cref="System.ArgumentNullException"><i>bytes</i> is a null reference.</exception>
        /// <exception cref="System.ArgumentException"><i>bytes</i> length is too short.</exception>
        IBlock CreateBlockFromBytes(byte[] bytes);

        /// <summary>
        /// Serializes the specified block to the specified array starting with the specified index.
        /// </summary>
        /// <param name="block">the block to serialize</param>
        /// <param name="array">the array where the serialized block should be stored</param>
        /// <param name="arrayIndex">the array index at which the serialized block
        /// should be stored in the array</param>
        /// <returns>the next index in the array</returns>
        /// <exception cref="System.ArgumentNullException">One of the arguments is a null reference.</exception>
        /// <exception cref="System.ArgumentOutOfRangeException"><i>arrayIndex</i> doesn't fall into
        /// the <i>array</i> boundaries.</exception>
        /// <exception cref="System.ArgumentException"><i>arrayIndex</i> or <i>array</i> length is invalid.</exception>
        int SerializeBlock(IBlock block, byte[] array, int arrayIndex);

        /// <summary>
        /// Serializes the specified block and returns a new array of block bytes.
        /// </summary>
        /// <param name="block">the block to serialize</param>
        /// <returns>the new array of block bytes</returns>
        /// <exception cref="System.ArgumentNullException"><i>block</i> is a null reference.</exception>
        byte[] SerializeBlock(IBlock block);

        /// <summary>
        /// Gets the number of bytes in block id (it is the fixed value).
        /// </summary>
        int BlockIdSizeBytes
        {
            get;
        }
    }
}
